package com.sicau.smarttraceplatform.config.security;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.sicau.smarttraceplatform.common.returning.ResultData;
import com.sicau.smarttraceplatform.entity.User;
import com.sicau.smarttraceplatform.entity.vo.user.UserVO;
import com.sicau.smarttraceplatform.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.dozer.Mapper;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author sxt
 * @version : 1.0.0
 */
@Component
@SuppressWarnings("JavaDoc")
@Slf4j
public class SecurityHandler implements
        LogoutSuccessHandler, AccessDeniedHandler, AuthenticationSuccessHandler, AuthenticationFailureHandler {


    @Resource
    private Mapper dozerMapper;

    /**
     * 处理没有权限
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @param e
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException {
        doResponse(httpServletResponse,
                new ResultData<Boolean>()
                        .OK()
                        .setResultIns("无访问权限")
                        .setObj(Boolean.FALSE));
    }

    /**
     * 处理注销成功
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @param authentication
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void onLogoutSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
        doResponse(httpServletResponse,
                new ResultData<Boolean>()
                        .OK()
                        .setResultIns("已安全退出")
                        .setObj(Boolean.TRUE));
    }


    /**
     * 响应信息
     *
     * @param response 当前响应对象
     * @param obj      响应结果对象
     */
    private void doResponse(HttpServletResponse response, Object obj) {
        response.setContentType("application/json; charset=utf-8");
        try {
            response.getWriter().write(JSONObject.toJSONString(obj, SerializerFeature.PrettyFormat, SerializerFeature.WriteMapNullValue));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Resource(name="sessionRepository")
    private RedisIndexedSessionRepository sessionRepository;

    @Override
    public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
//        TokenAuthenticationHandler tokenAuthenticationHandler = new TokenAuthenticationHandler();
        Object obj = authentication.getPrincipal();
        UserVO userVO = null;
        if (obj != null) {
            User user = (User) obj;
//            String token = tokenAuthenticationHandler.generateToken(JSONObject.toJSONString(user));
            String token = JwtUtil.generToken(user.getId().toString(), user.getName(), user.getAccount());
            httpServletResponse.addHeader("Authorization", "Bearer" + " " + token);
            userVO = dozerMapper.map(user, UserVO.class);
        }

        doResponse(httpServletResponse,
                new ResultData<>()
                        .OK()
                        .setResultIns("登陆成功")
                        .setObj(userVO));
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
        doResponse(httpServletResponse,
                new ResultData<Boolean>()
                        .FAILED()
                        .setResultIns("登陆失败")
                        .setObj(Boolean.FALSE));
    }
}
